# face_detection_app.py 升级版

import cv2
import numpy as np
import os
import tkinter as tk
from tkinter import filedialog, messagebox
from PIL import Image, ImageTk
import sys

def resource_path(relative_path):
    """获取资源的绝对路径，适用于开发环境和打包环境"""
    try:
        # PyInstaller创建临时文件夹，将路径存储在_MEIPASS中
        base_path = sys._MEIPASS
    except Exception:
        base_path = os.path.abspath(".")

    print(f"relative_path:{relative_path} , base_path{base_path}")
    
    return os.path.join(base_path, relative_path)

def find_cascade_file(filename):
        """多途径查找级联分类器文件"""

                # 尝试3: 在当前目录和子目录中搜索
        for root, dirs, files in os.walk('.'):
            if filename in files:
                print(f"root:{root} , fineName:{filename}")
                return os.path.join(root, filename)
            

        # 尝试1: 使用资源路径方法
        cascade_path = resource_path(filename)
        if os.path.exists(cascade_path):
            print(f"cascade_path:{cascade_path}")
            # return cascade_path
        
        # 尝试2: 在OpenCV数据目录中查找
        opencv_path = cv2.data.haarcascades + filename
        print(f"opencv_path:{opencv_path}")
        if os.path.exists(opencv_path):
            print(f"opencv_path:{opencv_path}")
            # return opencv_path
        

        return None




def detect_id_photo_background(image, edge_percent=0.1):
    """
    检测证件照背景颜色是否合法（仅检测边缘区域）
    
    Args:
        image: OpenCV图像 (BGR格式)
        edge_percent: 边缘区域占比 (0-1)
    
    Returns:
        tuple: (是否合法, 主要背景颜色, 置信度, 详细信息)
    """
    if image is None:
        return False, "未知", 0, "无法读取图像"
    
    height, width = image.shape[:2]
    
    # 计算边缘区域的像素范围
    edge_width = int(width * edge_percent)
    edge_height = int(height * edge_percent)
    
    # 提取四个边缘区域的像素
    edge_pixels = []
    
    # 上边缘
    if edge_height > 0:
        top_edge = image[:edge_height, :]
        edge_pixels.append(top_edge.reshape(-1, 3))
    
    # 左边缘（排除上下重叠部分）
    if edge_width > 0:
        left_edge = image[edge_height:-edge_height, :edge_width]
        edge_pixels.append(left_edge.reshape(-1, 3))
    
    # 右边缘（排除上下重叠部分）
    if edge_width > 0:
        right_edge = image[edge_height:-edge_height, -edge_width:]
        edge_pixels.append(right_edge.reshape(-1, 3))
    
    if not edge_pixels:
        return False, "未知", 0, "无法提取边缘像素"
    
    # 合并所有边缘像素
    all_edge_pixels = np.vstack(edge_pixels)
    
    if len(all_edge_pixels) == 0:
        return False, "未知", 0, "边缘区域无有效像素"
    
    # 转换为HSV颜色空间
    hsv_pixels = cv2.cvtColor(all_edge_pixels.reshape(-1, 1, 3), cv2.COLOR_BGR2HSV).reshape(-1, 3)
    
    # 定义合法背景颜色的HSV范围
    color_ranges = {
        '蓝色': ([90, 50, 50], [130, 255, 255]),      # 蓝色范围
        '白色': ([0, 0, 200], [180, 30, 255])         # 白色范围
    }
    
    # 统计各颜色范围的像素数量
    color_counts = {}
    total_pixels = len(hsv_pixels)
    
    for color_name, (lower, upper) in color_ranges.items():
        lower = np.array(lower, dtype=np.uint8)
        upper = np.array(upper, dtype=np.uint8)
        
        # 创建颜色掩码
        mask = np.zeros(total_pixels, dtype=bool)
        
        for i in range(total_pixels):
            h, s, v = hsv_pixels[i]
            if lower[0] <= h <= upper[0] and lower[1] <= s <= upper[1] and lower[2] <= v <= upper[2]:
                mask[i] = True
        
        color_counts[color_name] = np.sum(mask)
    

    
    # 计算各颜色的比例
    color_ratios = {color: count / total_pixels for color, count in color_counts.items()}
    
    # 计算合法颜色的总比例
    legal_colors = ['蓝色',  '白色']
    total_legal_ratio = max(color_ratios.get(color, 0) for color in legal_colors)
    
    # 找出主要颜色
    main_color = max(color_ratios, key=color_ratios.get) if color_ratios else "未知"
    main_ratio = color_ratios.get(main_color, 0)
    
    # 判断是否合法：合法颜色总占比超过60%
    is_legal = total_legal_ratio > 0.75
    
    # 生成详细信息
    details = f"背景检测结果（边缘{edge_percent*100:.0f}%区域）:\n"
    details += f"检测像素数: {total_pixels}\n"
    details += f"最大合法颜色占比: {total_legal_ratio:.1%}\n"
    details += f"主要颜色: {main_color} ({main_ratio:.1%})\n"
    details += f"合法性: {'合法' if is_legal else '非法'}\n\n"
    details += "各颜色占比:\n"

    print(details)
    
    # 按占比排序显示
    sorted_colors = sorted(color_ratios.items(), key=lambda x: x[1], reverse=True)
    for color, ratio in sorted_colors:
        status = "✓" if color in legal_colors else "✗"
        details += f"  {status} {color}: {ratio:.1%}\n"
    
    return is_legal, main_color, total_legal_ratio, details

class FaceDetectionApp:
    def __init__(self, root):
        self.root = root
        self.root.title("照片处理工具")
        self.root.geometry("700x560")
        self.root.minsize(700, 560)
        self.photo_min_size = (295,413)
        self.default_size = (114,156)
        
        # 初始化变量
        self.image_path = None
        self.original_image = None
        self.processed_image = None
        self.faces_info = []
        self.background_info = {}
        self.edge_percent = 0.1  # 边缘检测比例
        
        # 加载人脸检测器
        self.face_cascade = cv2.CascadeClassifier()
        cascade_path = find_cascade_file('haarcascade_frontalface_default.xml')
        
        # 如果模型文件不存在，尝试从OpenCV数据目录加载
        if not os.path.exists(cascade_path):
            cascade_path = cv2.data.haarcascades + 'haarcascade_frontalface_default.xml'
        
        if not self.face_cascade.load(cascade_path):
            messagebox.showerror("错误", f"无法加载人脸检测模型: {cascade_path}")
        
        # 创建界面
        self.create_widgets(root)
    


    def create_widgets(self, root):

        self.root = root
        # 移除标题栏和所有窗口控件
        # self.root.overrideredirect(True)
        
        # 设置窗口大小
        window_width = 700
        window_height = 500
        
        # 获取屏幕尺寸
        screen_width = root.winfo_screenwidth()
        screen_height = root.winfo_screenheight()
        
        # 计算窗口位置（屏幕中央）
        x_position = (screen_width - window_width) // 2
        y_position = (screen_height - window_height) // 2
        
        # 设置窗口位置和大小
        self.root.geometry(f"{window_width}x{window_height}+{x_position}+{y_position}")
        self.root.resizable(False, False)
        
        
         # 顶部区域 (10% 高度)
        top_frame = tk.Frame(root, bg='#CC0000', height=70)
        top_frame.pack(side=tk.TOP, fill=tk.X)
        top_frame.pack_propagate(False)
        

        title_label = tk.Label(top_frame, text="照 片 处 理 工 具", bg='#CC0000', 
                         fg='white', font=('黑体', 18, 'bold'))
        title_label.pack(side=tk.LEFT,expand=True , padx=(20,0))

        

# 顶部区域 (10% 高度)
        # 外层文本框架 - 高度160px，宽度填满

        middle_frame_red = tk.Frame(root, bg='red', height=450,  relief='solid')
        middle_frame_red.pack(fill=tk.BOTH , expand=True)
        middle_frame_white = tk.Frame(middle_frame_red, bg='white', height=450)
        middle_frame_white.pack(fill=tk.BOTH , expand=True, padx=(1, 1))





        text_frame = tk.Frame(middle_frame_white, bg='white', height=150,  relief='solid', padx=20)
        text_frame.pack(side=tk.TOP, fill=tk.X)
        text_frame.pack_propagate(False)  # 阻止自动调整大小，保持160px高度

        # 照片要求部分 - 标题和内容在同一行
        photo_req_frame = tk.Frame(text_frame , bg="white" , border=1)
        photo_req_frame.pack(fill=tk.X, pady=(10, 0), anchor=tk.NW)
        
        # 红底加粗的"照片要求"标签
        photo_title_label = tk.Label(photo_req_frame, 
                                    text="照片要求：", 
                                    font=("宋体", 11, "bold"),
                                    bg="white", 
                                    fg="red",
                                    anchor='nw',
                                    pady=2)
        photo_title_label.pack(side=tk.LEFT, anchor='n')

        photo_text = "报考人员本人近期免冠正面电子证件照片（蓝底或白底证件照，JPG、JPEG或PNG格式，照片宽度不低于295像素，高度不低于413像素）。"
        text_widget = tk.Text(photo_req_frame, 
                            font=("宋体", 11),
                            bg="white",
                            fg="#333333",
                            wrap=tk.WORD,
                            width=50,
                            height=3,
                            relief=tk.FLAT,  # 无边框
                            borderwidth=0,
                            spacing2=5)  # 设置行间距为5像素

        text_widget.insert(tk.END, photo_text)
        text_widget.config(state=tk.DISABLED)  # 设置为只读
        text_widget.pack(side=tk.LEFT, fill=tk.X, expand=True)


        
        # 有关说明部分 - 标题和内容在同一行
        instruction_frame = tk.Frame(text_frame , bg="white", border=1, height=120, width=540 )
        instruction_frame.pack(fill=tk.X, pady=(0, 5), anchor=tk.NW)
        
        # 红底加粗的"有关说明"标签
        instruction_title_label = tk.Label(instruction_frame, 
                                        text="有关说明：", 
                                        font=("宋体", 11, "bold"),
                                        bg="white", 
                                        anchor='nw',
                                        fg="red",
                                        pady=2)
        instruction_title_label.pack(side=tk.LEFT, padx=(0, 0), anchor='n')
        
        # 有关说明内容
        instruction_text = "点击“打开照片”按钮选择照片文件，符合要求的照片将显示在照片显示区域，点击“保存照片”按钮进行保存，保存后的照片大小在10KB左右，若照片不符合要求，需按信息提示重新选择符合要求的照片文件。"
        instruction_label = tk.Text(instruction_frame, 
                            font=("宋体", 11),
                            bg="white",
                            fg="#333333",
                            wrap=tk.WORD,
                            width=50,
                            height=4,
                            relief=tk.FLAT,  # 无边框
                            borderwidth=0,
                            spacing2=5)  # 设置行间距为5像素

        instruction_label.insert(tk.END, instruction_text)
        instruction_label.config(state=tk.DISABLED)  # 设置为只读
        instruction_label.pack(side=tk.LEFT, fill=tk.X, expand=True)


        # 中间区域 (70% 高度)
        middle_frame = tk.Frame(middle_frame_white, bg='white', height=300)
        middle_frame.pack(side=tk.TOP, fill=tk.BOTH, expand=True)
        middle_frame.pack_propagate(False)
        
        # 右侧按钮区域
        button_frame = tk.Frame(middle_frame, bg='white', width=300)
        button_frame.pack(side=tk.RIGHT, fill=tk.Y, padx=20)
        button_frame.pack_propagate(False)
        
        # 创建三个按钮
        self.btn_open = self.create_image_button(button_frame, self.select_image, "res/open.png")
        self.btn_open.pack(pady=12)
        
        # 保存按钮 - 使用修改后的样式
        self.btn_save = self.create_image_button(button_frame, self.save_result, "res/save.png")
        self.btn_save.pack(pady=12)
        self.btn_save.config(state=tk.DISABLED)
        
        # 退出操作按钮

        self.btn_exit = self.create_image_button(button_frame, self.root.destroy, "res/exit.png")
        self.btn_exit.pack(pady=12)

        photo_frame = tk.Frame(middle_frame, bg='white', relief=tk.SUNKEN, width=240, height=300)
        photo_frame.pack(side=tk.LEFT,anchor=tk.NW, padx=(80, 20)) 
        photo_frame.pack_propagate(False)


        image_frame = tk.Frame(photo_frame, bg='#ffdddd', relief=tk.SUNKEN, width=180, height=240)
        image_frame.pack(side=tk.TOP, anchor=tk.NW, padx=(20, 20), pady=(10,0))  # 移除 fill 和 expand 参数
        image_frame.pack_propagate(False)  # 添加这行阻止自动调整
        # 图片显示区域
        self.canvas = tk.Canvas(image_frame, bg='white', relief=tk.SUNKEN)
        self.canvas.pack( padx=6, pady=6)


        image = Image.open("res/example.jpg")
        resized_image = image.resize((180, 240), Image.LANCZOS)
        # 将PIL图像转换为Tkinter可用的PhotoImage
        photo = ImageTk.PhotoImage(resized_image)
        
        
        # 在Canvas上创建图像项
        self.canvas.create_image(0, 0, anchor=tk.NW, image=photo)
        
        # 调整Canvas大小以匹配图片尺寸
        self.canvas.config(width=180, height=240)
        
        # 保持对photo的引用，防止被垃圾回收
        self.canvas.image = photo

        # 信息提示区域

        msg_frame = tk.Frame(photo_frame, bg='#FFEAE6',  width=180, height=30, bd=1)
        msg_frame.pack(side=tk.LEFT, padx=(20, 20), pady=1)  # 移除 fill 和 expand 参数
        msg_frame.pack_propagate(False)  # 添加这行阻止自动调整

        self.info_label = tk.Label(msg_frame, text="标准证件照示例", bg='#FFEAE6', fg='#333333' ,
                                  font=('宋体', 10), height=2, wraplength=400, bd=1)
        self.info_label.pack(fill=tk.X, padx=10)
        
        # 底部区域 (10% 高度)
        bottom_frame = tk.Frame(root, bg='#F33121', height=30, bd=1)
        bottom_frame.pack(side=tk.BOTTOM, fill=tk.X)
        bottom_frame.pack_propagate(False)
        
        # 版权信息
        copyright_text = "版权所有@河南云数聚网络科技有限公司"
        copyright_label = tk.Label(bottom_frame, text=copyright_text, 
                                  bg='#F33121', fg='white', font=('宋体', 10))
        copyright_label.pack(expand=True)
        
        # 存储当前图片
        self.current_image = None
        self.photo = None
        
        # 添加窗口拖动功能
        self.start_x = None
        self.start_y = None
        top_frame.bind("<ButtonPress-1>", self.start_move)
        top_frame.bind("<ButtonRelease-1>", self.stop_move)
        top_frame.bind("<B1-Motion>", self.do_move)
        

        
    def start_move(self, event):
        self.start_x = event.x
        self.start_y = event.y
        
    def stop_move(self, event):
        self.start_x = None
        self.start_y = None
        
    def do_move(self, event):
        if self.start_x is not None and self.start_y is not None:
            x = self.root.winfo_x() + (event.x - self.start_x)
            y = self.root.winfo_y() + (event.y - self.start_y)
            self.root.geometry(f"+{x}+{y}")

    def create_image_button(self, parent, command, image_path=None):
        """创建带图片的按钮"""
        if image_path and os.path.exists(image_path):
            # 加载并调整图片大小
            img = Image.open(image_path)
            photo = ImageTk.PhotoImage(img)
            
            # 使用标准tk.Button而不是ttk.Button
            btn = tk.Button(parent, 
                          command=command, 
                          image=photo,
                          borderwidth=0,      # 设置边框宽度为0
                          highlightthickness=0, # 移除高亮边框
                          relief='flat',       # 设置平坦样式
                          bg='white',          # 设置背景色与父容器相同
                          activebackground='white' # 设置激活时背景色
                         )
            btn.image = photo  # 保持引用
        else:
            btn = tk.Button(parent, 
                          command=command,
                          borderwidth=0,
                          highlightthickness=0,
                          relief='flat',
                          bg='white',
                          activebackground='white')
            
        return btn
    
    
    def select_image(self):
        file_path = filedialog.askopenfilename(
            title="选择图像文件",
            filetypes=[("图像文件", "*.jpg *.jpeg *.png *.bmp *.tiff"), ("所有文件", "*.*")]
        )
        
        if file_path:
            self.image_path = file_path
            self.load_image()
            # self.process_btn.config(state=tk.NORMAL)
            # self.visualize_btn.config(state=tk.NORMAL)
            
    
        
    
    def resize_image(self,image, max_size=(114, 156)):
        """
        调整图片尺寸：先等比压缩，然后裁剪中间部分
        
        Args:
            image: 输入的OpenCV图像
            max_size: 目标尺寸 (宽, 高)
        
        Returns:
            调整后的图像，如果不需要调整则返回原图
        """
        if image is None:
            return None
        
        # 获取原始尺寸
        original_height, original_width = image.shape[:2]
        target_width, target_height = max_size
        
        hwrate = original_height / original_width
        print(f"长高比: {hwrate}")
        
        # 检查图片是否过小
        if original_width < target_width and original_height < target_height:
            messagebox.showerror("错误", "照片尺寸过小，请上传分辨率不低于295像素(宽) × 413像素(高) 的照片。")
            self.info_label.config(text= "照片尺寸过小")
            return None
        
        # 第一步：等比压缩，确保宽度不低于target_width或高度不低于target_height
        # 计算缩放比例，取能够满足至少一个维度不低于目标值的最大比例
        ratio = max(target_width / original_width, target_height / original_height)
        new_width = max(int(original_width * ratio) , max_size[0])
        new_height = max(int(original_height * ratio)   ,max_size[1] ) 
        
        # 等比缩放
        resized_image = cv2.resize(image, (new_width, new_height), interpolation=cv2.INTER_AREA)
        print(f"等比缩放: {original_width}x{original_height} -> {new_width}x{new_height}")
        
        # 第二步：裁剪中间部分到目标尺寸
        # 计算裁剪的起始位置
        start_x = (new_width - target_width) // 2
        start_y = (new_height - target_height) // 2
        
        # 裁剪图像
        cropped_image = resized_image[start_y:start_y + target_height, start_x:start_x + target_width]
        print(f"中心裁剪: {new_width}x{new_height} -> {target_width}x{target_height}")
        
        return cropped_image



    def load_image(self):
        try:
            # 使用imdecode读取图像，避免中文路径问题
            with open(self.image_path, 'rb') as f:
                img_data = np.frombuffer(f.read(), np.uint8)
            self.original_image = cv2.imdecode(img_data, cv2.IMREAD_COLOR)
            
            if self.original_image is None:
                messagebox.showerror("错误", "无法读取图片")
                return

            # 清空处理后的图像显示
            self.process_image()
            
        except Exception as e:
            messagebox.showerror("错误", f"加载图像时出错: {str(e)}")
    
    
    def display_image(self, image, canvas):
        try:
            # 调整图像大小以适应画布
            canvas.update_idletasks()  # 确保画布尺寸已更新
            canvas_width = canvas.winfo_width()
            canvas_height = canvas.winfo_height()
            
            if canvas_width <= 1 or canvas_height <= 1:
                canvas_width = 400
                canvas_height = 300
            
            height, width = image.shape[:2]
            
            # 计算缩放比例
            scale = min(canvas_width / width, canvas_height / height)
            new_width = int(width * scale)
            new_height = int(height * scale)
            
            if new_width > 0 and new_height > 0:
                image = cv2.resize(image, (new_width, new_height))
            
            # 转换颜色空间 BGR to RGB
            image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
            pil_image = Image.fromarray(image_rgb)
            
            # 更新画布
            canvas.delete("all")
            photo_image = ImageTk.PhotoImage(pil_image)
            canvas.image = photo_image  # 保持引用避免垃圾回收
            canvas.create_image(canvas_width//2, canvas_height//2, anchor=tk.CENTER, image=photo_image)
            
        except Exception as e:
            messagebox.showerror("错误", f"显示图像时出错: {str(e)}")
    
    def process_image(self):
        if self.original_image is None:
            return
        
        try:
            # 获取用户选择的尺寸
            max_size = self.default_size

            # 调整图像尺寸
            processed_image = self.resize_image(self.original_image.copy(), max_size)
            if processed_image is None:
                return
            
            # 检测证件照背景（仅边缘区域）
            is_legal, main_color, legal_ratio, bg_details = detect_id_photo_background(processed_image, self.edge_percent)
            

            # 如果不合法，显示警告
            if not is_legal:
                self.info_label.config(text= "照片背景不符合要求")
                messagebox.showerror("错误", "照片背景不符合要求，请上传背景为蓝色或白色的标准证件照。")
                return
            

            # 转换为灰度图进行人脸检测
            gray = cv2.cvtColor(processed_image, cv2.COLOR_BGR2GRAY)
            
            # 检测人脸
            faces = self.face_cascade.detectMultiScale(gray, 1.2, 5)
            
            self.faces_info = []
            result_text = f"检测到 {len(faces)} 张人脸\n"
            result_text += f"处理尺寸: {processed_image.shape[1]}x{processed_image.shape[0]}\n"
            result_text += f"背景检测: {main_color} (合法占比: {legal_ratio:.1%})\n\n"

            print(result_text)
            num =0
            # 处理每张人脸
            for i, (x, y, w, h) in enumerate(faces):
                
                
                # 提取人脸区域
                face_roi = gray[y:y+h, x:x+w]
                
                # 计算清晰度
                clarity = self.calculate_clarity(face_roi)
                clarity_level = self.evaluate_clarity(clarity)
                if clarity>200 and clarity< 2200:
                    num +=1

                print(f"人脸识别指数:{clarity}, 次数{i}")
                
            
                # 保存人脸信息
                self.faces_info.append({
                    'index': i+1,
                    'position': (x, y),
                    'size': (w, h),
                    'clarity': clarity,
                    'level': clarity_level
                })

            if num == 0 :
                if len(faces)>0:
                    messagebox.showerror("错误", "人脸识别异常，请上传人像清晰、正面免冠的证件照。")
                    self.info_label.config(text= "人脸识别异常")
                    self.btn_save.config(state=tk.NORMAL)
                else:
                    messagebox.showerror("错误", "未识别到人脸，请上传人像清晰、正面免冠的证件照。")
                    self.info_label.config(text= "未识别到人脸")
                    return

                
            else:
                # 启用保存按钮
                self.btn_save.config(state=tk.NORMAL)
        
                self.info_label.config(text= "符合标准，保存退出")
                
            
            # 显示处理后的图像
            self.processed_image = processed_image
            self.display_image(processed_image, self.canvas)

            # 保存背景信息
            self.background_info = {
                'is_legal': is_legal,
                'main_color': main_color,
                'legal_ratio': legal_ratio,
                'details': bg_details
            }
            
        except Exception as e:
            messagebox.showerror("错误", f"处理图像时出错: {str(e)}")
    
    def calculate_clarity(self, image):
        """计算图像清晰度"""
        if image.size == 0:
            return 0
        laplacian = cv2.Laplacian(image, cv2.CV_64F)
        return laplacian.var()
    
    def evaluate_clarity(self, score):
        """评估清晰度等级"""
        if score>100 :return True
        else : return False
    

    def save_result(self):
        if self.processed_image is None:
            return
        
        try:
            # 获取用户文档目录作为默认保存位置
            documents_dir = os.path.join(os.path.expanduser("~"), "Documents")
            if not os.path.exists(documents_dir):
                documents_dir = os.path.expanduser("~")  # 回退到用户主目录
            
            file_path = filedialog.asksaveasfilename(
                title="保存结果图像",
                defaultextension=".jpg",
                initialfile="报名照片.jpg",
                initialdir=documents_dir,
                filetypes=[("JPEG图像", "*.jpg"), ("PNG图像", "*.png"), ("所有文件", "*.*")]
            )
            
            if not file_path:  # 用户取消了保存
                return
            
            # 检查路径长度
            if len(os.path.abspath(file_path)) > 260:
                messagebox.showerror("错误", "文件路径过长，请选择较短的路径或文件名")
                return
                
            # 检查目录权限
            save_dir = os.path.dirname(file_path)
            if not os.path.exists(save_dir):
                try:
                    os.makedirs(save_dir)
                except OSError:
                    messagebox.showerror("错误", f"无法创建目录: {save_dir}")
                    return
                    
            if not os.access(save_dir, os.W_OK):
                messagebox.showerror("错误", f"没有权限在目录 {save_dir} 中保存文件")
                return
            


            # 保存图像
            success = cv2.imwrite(file_path, self.processed_image)
            
            # 验证保存结果
            if success and os.path.exists(file_path) and os.path.getsize(file_path) > 0:
                messagebox.showinfo("保存成功", f"照片已保存到:\n{file_path}")
            else:
                # 尝试使用PIL保存作为备选方案
                try:
                    from PIL import Image
                    img_rgb = cv2.cvtColor(self.processed_image, cv2.COLOR_BGR2RGB)
                    pil_image = Image.fromarray(img_rgb)
                    pil_image.save(file_path, 'JPEG')
                    if os.path.exists(file_path) and os.path.getsize(file_path) > 0:
                        messagebox.showinfo("保存成功", f"照片已保存到:\n{file_path}\n")
                    else:
                        messagebox.showerror("错误", "文件保存失败，请尝试其他位置")
                except Exception as e:
                    messagebox.showerror("错误", f"文件保存失败: {str(e)}")

        except Exception as e:
            messagebox.showerror("错误", f"保存结果时出错: {str(e)}")

# 主程序入口
def main():
    
    root = tk.Tk()
    app = FaceDetectionApp(root)
    root.iconbitmap('favicon2.ico')
    root.mainloop()


if __name__ == "__main__":
    main()